package com.cnswhy.cloud.server.app.handler;

import cn.hutool.core.util.StrUtil;
import com.cnswhy.cloud.common.core.exception.BizException;
import com.cnswhy.cloud.common.core.exception.code.ExceptionCode;
import com.cnswhy.cloud.server.core.vo.RespVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author cnswhy
 */
@ControllerAdvice(annotations= {Controller.class})
@Slf4j
public class GlobalExceptionHandler {
    /**
     * spring 封装的参数验证异常， 在conttoller中没有写result参数时，会进入
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public RespVo methodArgumentNotValidException(MethodArgumentNotValidException ex, HttpServletRequest request) {
        log.warn("MethodArgumentNotValidException:", ex);
        return new RespVo(ExceptionCode.BASE_VALID_PARAM.getCode(), ex.getBindingResult().getFieldError().getDefaultMessage());
    }
    /**
     * 系统异常处理，比如：404,500
     * @param req
     * @param resp
     * @param e
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public RespVo defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        log.error("服务异常", e);
        RespVo response = new RespVo(RespVo.CODE_ERROR);
        response.setMessage("服务器离家出走啦！！！");
        response.setResult(null);
        return response;
    }

    /**
     * 运行时异常
     * @param exception
     * @return
     */
    @ExceptionHandler({ RuntimeException.class })
    @ResponseBody
    public RespVo processException(RuntimeException exception) {
        //exception.printStackTrace();
        //log.info(exception.getMessage());
        log.info("自定义异常处理-RuntimeException：{}", exception.getMessage());
        RespVo response = new RespVo(RespVo.CODE_ERROR);
        if(exception.getMessage().length() < 32){
            response.setMessage(exception.getMessage());
        }else{
            response.setMessage("服务器500!");
        }
        response.setResult(null);
        return response;
    }
/*
    *//**
     *
     * @Description:交易异常
     * @param e
     * @return
     * RespVo
     * @author: tanhr
     * @time:2018年7月25日 下午6:51:51
     *//*
    @ExceptionHandler({ TradeBusExecption.class })
    @ResponseBody
    public RespVo processBuyException(TradeBusExecption e) {
        log.info("交易出现异常："+e.getReason());
        RespVo response = new RespVo(RespVo.CODE_ERROR,e.getReason(),e.getReason());
        return response;
    }

    *//**
     *
     * @Description: TODO(这里用一句话描述这个方法的作用)
     * @param @param e
     * @param @return    设定文件
     * @return RespVo    返回类型
     * @throws
     *//*
    @ExceptionHandler({ PayExecption.class })
    @ResponseBody
    public RespVo processPayException(TradeBusExecption e) {
        log.info("在线支付出现异常："+e.getReason());
        RespVo response = new RespVo(RespVo.CODE_ERROR,e.getReason(),e.getReason());
        return response;
    }*/


    /**
     * @Description:TODO
     * @param e
     * @return
     * RespVo
     * @author: tanhr
     * @time:2018年7月25日 下午7:03:24
     */
    @ExceptionHandler({ BizException.class })
    @ResponseBody
    public RespVo processBuyException(BizException e) {
        log.info("登录超时："+e.getMessage());
        RespVo response = new RespVo();
        response.setMessage(e.getMessage());
        response.setCode(e.getCode());
        return response;
    }

    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public RespVo bindException(BindException ex, HttpServletRequest request) {
        log.warn("BindException:", ex);
        try {
            String msgs = ex.getBindingResult().getFieldError().getDefaultMessage();
            if (StrUtil.isNotEmpty(msgs)) {
                return new RespVo(ExceptionCode.PARAM_EX.getCode(),msgs);
            }
        } catch (Exception ee) {
        }
        StringBuilder msg = new StringBuilder();
        List<FieldError> fieldErrors = ex.getFieldErrors();
        fieldErrors.forEach((oe) ->
                msg.append("参数:[").append(oe.getObjectName())
                        .append(".").append(oe.getField())
                        .append("]的传入值:[").append(oe.getRejectedValue()).append("]与预期的字段类型不匹配.")
        );
        return new RespVo(ExceptionCode.PARAM_EX.getCode(),msg.toString());
    }
}
